package com.dianban.plugin.weixinpay;

import com.alibaba.fastjson.JSONObject;
import com.dianban.base.ResultCode;
import com.dianban.base.ResultVo;
import com.dianban.config.redis.RedisUtil;
import com.dianban.utils.MD5Utils;
import com.dianban.weixin.util.WeiXinUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 语雀API文档地址:https://www.yuque.com/leshuazf/doc
 * 进件key：17B10781A8C5178870197906F71749D8
 * 交易key：a1613a0e7cb9d3a51e33784ee4d212ac
 * 验证签名工具地址：https://jh.leshuazf.com/#/signature
 * <p>
 * 服务商编号：10
 * 测试商户号号：0000000018
 * 进件接口域名:http://t-saas-mch.lepass.cn/apiv2
 * 交易接口:https://t-paygate.lepass.cn/cgi-bin/lepos_pay_gateway.cgi
 * <p>
 * ****注意事项****
 * 1.不要支付大额度，会实时扣款（限制最大金额2.00元）
 * 2.所有涉及到金额的单位都位分，币种为RMB，最小为1分，不允许出现小数
 * 3.交易需用提供的测试商户号测试
 * 4.小程序、公众号需在正式环境验证(测试环境不支持)
 */
@Component("LeshuaPayFacePlugin")
public class LeshuaPayFacePlugin {

    private Logger logger = LoggerFactory.getLogger(LeshuaPayFacePlugin.class);

    //测试环境域名：https://t-paygate.lepass.cn
    //生产环境域名：https://paygate.leshuazf.com
    //统一下单接口地址：/cgi-bin/lepos_pay_gateway.cgi
    //刷脸支付接口地址：/open_api/get_wxpayface_authinfo.cgi
    private final String leShuaPayfaceAuthinfoUrl = "https://paymeans.leshuazf.com/open_api/get_wxpayface_authinfo.cgi";

    private final String micropayUrl = "https://paygate.leshuazf.com/cgi-bin/lepos_pay_gateway.cgi";

    public String getSiteUrl() {
        return "http://yun.dianbang-st.com:9006/api/weixin/leshua/asyncNotify/";
        //return "https://rongyaotupay.aokxm.com/api/weixin/leshua/asyncNotify/";
    }

    public String getNotifyUrl(String sn) {
        return getSiteUrl() + sn;
    }

    //@Value("${leshua.merchant_id}")
    @Value("${leshua.iyijia.merchant_id}")
    private String merchantId;
    @Value("${leshua.appSecret}")
    private String appSecret;
    @Value("${leshua.returnAppSecret}")
    private String returnAppSecret;
    @Value("${weixin.appId}")
    private String appId;
    //@Value("${leshua.mch_id}")
    @Value("${leshua.iyijia.mch_id}")
    private String mchId;

    public ResultVo getWxpayfaceAuthinfo(String store_id, String store_name, String device_id, String rawdata, String screenMac) {
        HashMap<String, Object> params = new HashMap<String, Object>();
        HashMap<String, Object> resultMap = new HashMap<String, Object>();
        String keyRedis = MD5Utils.getMD5Str(store_id + device_id + screenMac);
        Object objRedis = RedisUtil.get(keyRedis);
        if (objRedis != null) {
            resultMap = (HashMap<String, Object>) objRedis;
            return ResultVo.success(resultMap, "成功");
        }
        String noncestr = WeiXinUtils.CreateNoncestr();
        String now = String.valueOf(new Date().getTime()).substring(0, 10);

        //params.put("sub_appid",appId);//商户公众账号 ID
        params.put("sub_mch_id", mchId);//乐刷微信商户号
        params.put("merchant_id", merchantId);//乐刷商户号
        params.put("rawdata", rawdata);//初始化数据。由微信人脸SDK的接口返回。
        params.put("store_id", store_id);//门店编号， 由商户定义， 各门店唯一。
        params.put("store_name", store_name);//门店名称，由商户定义。（可用于展示）
        params.put("device_id", device_id);//终端设备编号，由商户定义。

       /* params.put("appid",appId); //商户号绑定的公众号/小程序 appid
        params.put("mch_id",mchId); //商户号
        params.put("now",now); //取当前时间，10位unix时间戳。 例如：1239878956
        params.put("version","1"); //版本号。固定为1
        params.put("sign_type","MD5"); // 签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
        params.put("nonce_str",noncestr); // 随机字符串，不长于32位*/
        try {
            String sign = getSign(params);
            params.put("sign", sign); // 参数签名
            String urlQueryParams = WeiXinUtils.FormatUrlQueryParaMap(params, true);
            logger.info("urlQueryParams:" + urlQueryParams);
            HttpClient httpClient = new DefaultHttpClient();
            String url = leShuaPayfaceAuthinfoUrl + "?" + urlQueryParams;
            HttpPost httpPost = new HttpPost(url);
            //      httpPost.setEntity(new StringEntity(bizQueryParams, "UTF-8"));
            HttpResponse response = httpClient.execute(httpPost);
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            logger.info("result:" + result);
            resultMap = WeiXinUtils.doXMLParse(result);
            String status = (String) resultMap.get("status");
            if (StringUtils.isNotBlank(status) && "2".equals(status)) {
                Integer expires_in = Integer.parseInt(resultMap.get("expires_in").toString());
                RedisUtil.set(keyRedis, resultMap, (expires_in - 60));
                return ResultVo.success(resultMap, "成功");
            } else {
                String resp_code = (String) resultMap.get("resp_code");
                String resp_msg = (String) resultMap.get("resp_msg");
                return ResultVo.error(resp_code, resp_msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultVo.error(ResultCode.FAIL);
        }
    }

    public HashMap<String, Object> getWxpayfaceCodeParams(String store_id, String authinfo) {
        HashMap<String, Object> params = new HashMap<String, Object>();
        params.put("appid",appId); //商户号绑定的公众号/小程序 appid
        params.put("mch_id", mchId); //商户号
        params.put("store_id", store_id);//门店编号， 由商户定义， 各门店唯一。
        params.put("face_authtype", "FACEPAY");//FACEPAY: 人脸凭证，常用于人脸支付
        params.put("authinfo", authinfo);//调用凭证
        params.put("ask_face_permit", "1");//支付成功页是否需要展示人脸识别授权项。展示：1
        params.put("face_code_type", "1");//目标face_code类型，可选值："1"，刷卡付款码：18位数字，通过「付款码支付/被扫支付」接口完成支付。如果不填写则默认为"0"
        return params;
    }

    public ResultVo micropay(String store_id, String body, String out_trade_no, int total_fee, String spbill_create_ip, String auth_code) {
        String noncestr = WeiXinUtils.CreateNoncestr();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("service", "upload_authcode"); //条码支付（被扫：B扫C）
        params.put("auth_code", auth_code);//扫码支付付款码，设备读取用户微信中的条码或者二维码信息 （注：用户付款码条形码规则：18位纯数字，以10、11、12、13、14、15开头）
        params.put("merchant_id", merchantId);//乐刷商户号
        params.put("third_order_id", out_trade_no);//商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|*且在同一个商户号下唯一
        params.put("amount", total_fee);//订单总金额，单位为分，只能为整数
        params.put("nonce_str", noncestr); // 随机字符串，不长于32位
        params.put("notify_url", URLEncoder.encode(getNotifyUrl(out_trade_no))); // 接收乐刷通知的URL，需做UrlEncode 处理，
        params.put("body", body); //门店付款码	付款码支付	店名-销售商品类目	小张南山店-超市	线下门店支付
        params.put("client_ip", spbill_create_ip);//支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP
        try {
            String sign = getSign(params);
            params.put("sign", sign); // 参数签名
            String urlQueryParams = WeiXinUtils.FormatUrlQueryParaMap(params, true);
            logger.info("urlQueryParams:" + urlQueryParams);
            HttpClient httpClient = new DefaultHttpClient();
            String url = micropayUrl + "?" + urlQueryParams;
            HttpPost httpPost = new HttpPost(url);
            HttpResponse response = httpClient.execute(httpPost);
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            logger.info("result:" + result);
            HashMap<String, Object> resultMap = WeiXinUtils.doXMLParse(result);
            String status = (String) resultMap.get("status");
            if (StringUtils.isNotBlank(status) && "2".equals(status)) {
                Map<String, Object> returnMap = new HashMap<>();
                BigDecimal paymentAmount = new BigDecimal(total_fee).multiply(new BigDecimal(100));
                returnMap.put("paymentAmount", paymentAmount); //支付的微信金额
                return ResultVo.success(returnMap, "支付成功");
            } else {
                String resp_msg = (String) resultMap.get("resp_msg");
                String resp_code = (String) resultMap.get("resp_code");
                return ResultVo.error(resp_code, resp_msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultVo.error(ResultCode.FAIL);
        }
    }

    /**
     * 作用：生成签名
     */
    public String getSign(Map<String, Object> params) throws Exception {
        // 签名步骤一：按字典序排序参数
        String str = WeiXinUtils.FormatBizQueryParaMap(params, false);
        // 签名步骤二：在string后加入KEY
        str += "&key=" + appSecret;
        // 签名步骤三：MD5加密 签名步骤四：所有字符转为大写
        str = MD5Utils.getMD5Str(str).toUpperCase();
        return str;
    }

    public String getSignReturn(Map<String, Object> params) throws Exception {
        // 签名步骤一：按字典序排序参数
        String str = WeiXinUtils.FormatBizQueryParaMap(params, false);
        // 签名步骤二：在string后加入KEY
        str += "&key=" + returnAppSecret;
        // 签名步骤三：MD5加密 签名步骤四：所有字符转为大写
        str = MD5Utils.getMD5Str(str).toUpperCase();
        return str;
    }

    public String verifyNotify(String sn, BigDecimal amount, HttpServletRequest request) {
        String tradeSn = "";
        try {
            Map<String, Object> map = new HashMap();
            StringBuffer info = new StringBuffer();
            InputStream in = request.getInputStream();
            BufferedInputStream buf = new BufferedInputStream(in);
            byte[] buffer = new byte[1024];
            int iRead;
            while ((iRead = buf.read(buffer)) != -1) {
                info.append(new String(buffer, 0, iRead, "UTF-8"));
            }
            map = WeiXinUtils.doXMLParse(info.toString());
            if (map == null || map.isEmpty()) {
                return tradeSn;
            }
            logger.info("leshua 刷脸支付回调:{}", JSONObject.toJSONString(map));
            if (map.get("status") != null && "2".equals(map.get("status"))) {
                String sign = getSignReturn(map);
                logger.info("leshua 小程序支付回调参数签名:{}", sign);
                if (/*sign.equals(map.get("sign"))
                        && */sn.equals(map.get("third_order_id"))
                        && merchantId.equals(map.get("merchant_id"))
                        && amount.multiply(new BigDecimal(100)).compareTo(new BigDecimal((String) map.get("amount"))) == 0) {
                    tradeSn = String.valueOf(map.get("leshua_order_id"));
                    return tradeSn;
                }
            }
            return tradeSn;
        } catch (Exception e) {
            e.printStackTrace();
            return tradeSn;
        }
    }

    public String getNotifyMessage() {
        return "000000";
    }


}
